home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cfengine-1.5.3 / src / misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-14  |  15.8 KB  |  655 lines

  1. /* cfengine for GNU
  2.  
  3.         Copyright (C) 1995
  4.         Free Software Foundation, Inc.
  5.  
  6.    This file is part of GNU cfengine - written and maintained 
  7.    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
  8.    Dept. of Theoretical physics, University of Oslo
  9.  
  10.    This program is free software; you can redistribute it and/or modify it
  11.    under the terms of the GNU General Public License as published by the
  12.    Free Software Foundation; either version 2, or (at your option) any
  13.    later version.
  14.  
  15.    This program is distributed in the hope that it will be useful,
  16.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.    GNU General Public License for more details.
  19.  
  20.   You should have received a copy of the GNU General Public License
  21.   along with this program; if not, write to the Free Software
  22.   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
  23.  
  24. */
  25.  
  26.  
  27. /*********************************************************************/
  28. /*                                                                   */
  29. /*  TOOLKITS: "object" library                                       */
  30. /*                                                                   */
  31. /*********************************************************************/
  32.  
  33. #define INET
  34.  
  35. #include "cf.defs.h"
  36. #include "cf.extern.h"
  37. #include "../pub/global.h"
  38. #include "../pub/md5.h"
  39.  
  40. #ifdef HAVE_DB_2_H
  41. # include <db_2.h>
  42. #else
  43. # if defined HAVE_DB_H && defined HAVE_DB_185_H
  44. #  include <db.h>
  45. # endif
  46. #endif
  47.  
  48. #if HAVE_DB_DB_H
  49. # include <db/db.h>
  50. #endif
  51.  
  52. /*******************************************************************/
  53.  
  54. GetNameInfo()
  55.  
  56. { int i, sz, found = false;
  57.   char *sp,*sp2;
  58.   time_t tloc;
  59.   struct hostent *hp;
  60.   struct sockaddr_in cin;
  61. #ifdef AIX
  62.   char real_version[_SYS_NMLN];
  63. #endif
  64.   
  65. VFQNAME[0] = VUQNAME[0] = '\0';
  66.   
  67. if (uname(&VSYSNAME) == -1)
  68.    {
  69.    perror("uname ");
  70.    FatalError("Uname couldn't get kernel name info!!\n");
  71.    }
  72.  
  73. #ifdef AIX
  74. snprintf(real_version, _SYS_NMLN, "%s.%s", VSYSNAME.version, VSYSNAME.release);
  75. strncpy(VSYSNAME.release, real_version, _SYS_NMLN);
  76. #endif 
  77.  
  78. for (sp = VSYSNAME.sysname; *sp != '\0'; sp++)
  79.    {
  80.    *sp = ToLower(*sp);
  81.    }
  82.  
  83. for (sp = VSYSNAME.machine; *sp != '\0'; sp++)
  84.    {
  85.    *sp = ToLower(*sp);
  86.    }
  87.  
  88.  
  89. for (i = 0; CLASSATTRIBUTES[i][0] != '\0'; i++)
  90.    {
  91.    if (WildMatch(CLASSATTRIBUTES[i][0],VSYSNAME.sysname))
  92.       {
  93.       if (WildMatch(CLASSATTRIBUTES[i][1],VSYSNAME.machine))
  94.          {
  95.          if (WildMatch(CLASSATTRIBUTES[i][2],VSYSNAME.release))
  96.             {
  97.         if (UNDERSCORE_CLASSES)
  98.            {
  99.            sprintf(VBUFF,"_%s",CLASSTEXT[i]);
  100.            AddClassToHeap(VBUFF);
  101.            }
  102.         else
  103.            {
  104.                AddClassToHeap(CLASSTEXT[i]);
  105.            }
  106.             found = true;
  107.             break;
  108.             }
  109.          }
  110.       else
  111.          {
  112.          Debug2("Cfengine: I recognize %s but not %s\n",VSYSNAME.sysname,VSYSNAME.machine);
  113.          continue;
  114.          }
  115.       }
  116.    }
  117.  
  118. if ((sp = malloc(strlen(VSYSNAME.nodename)+1)) == NULL)
  119.    {
  120.    FatalError("malloc failure in initialize()");
  121.    }
  122.  
  123. strcpy(sp,VSYSNAME.nodename);
  124. SetDomainName(sp);
  125.  
  126. strcpy(VPREFIX,VSYSNAME.nodename);
  127.  
  128. for (sp2=sp; *sp2 != '\0'; sp2++)  /* Truncate fully qualified name */
  129.    {
  130.    if (*sp2 == '.')
  131.       {
  132.       *sp2 = '\0';
  133.       Debug("Truncating fully qualified hostname %s to %s\n",VSYSNAME.nodename,sp);
  134.       break;
  135.       }
  136.    }
  137.  
  138.  
  139. VDEFAULTBINSERVER.name = sp;
  140.  
  141. AddClassToHeap(CanonifyName(sp));
  142.  
  143. VSYSTEMHARDCLASS = (enum classes) i;
  144.  
  145.  
  146. if ((tloc = time((time_t *)NULL)) == -1)
  147.    {
  148.    printf("Couldn't read system clock\n");
  149.    }
  150.  
  151.  
  152. CFSTARTTIME = tloc;
  153.  
  154. sprintf(VBUFF,"%s",ctime(&tloc));
  155. AddTimeClass(VBUFF);
  156.  
  157.  
  158. if (VERBOSE)
  159.    {
  160.    if (UNDERSCORE_CLASSES)
  161.       {
  162.       sprintf(VBUFF,"_%s",CLASSTEXT[i]);
  163.       }
  164.    else
  165.       {
  166.       sprintf(VBUFF,"%s",CLASSTEXT[i]);
  167.       }
  168.  
  169.    if (ISCFENGINE)
  170.       {
  171.       printf ("GNU Configuration Engine - \n%s\n%s\n\n",VERSION,COPYRIGHT);
  172.       }
  173.    else
  174.       {
  175.       printf ("GNU Cfengine server daemon - \n%s\n%s\n\n",VERSION,COPYRIGHT);      
  176.       }
  177.  
  178.    printf ("------------------------------------------------------------------------\n\n");
  179.    printf ("Host name is: %s\n",VSYSNAME.nodename);
  180.    printf ("Operating System Type is %s\n",VSYSNAME.sysname);
  181.    printf ("Operating System Release is %s\n",VSYSNAME.release);
  182.    printf ("Architecture = %s\n\n\n",VSYSNAME.machine);
  183.    printf ("Using internal soft-class %s for host %s\n\n",VBUFF,VSYSNAME.nodename);
  184.    printf ("The time is now %s\n\n",ctime(&tloc));
  185.    printf ("------------------------------------------------------------------------\n\n");
  186.  
  187.    }
  188.  
  189. sprintf(VBUFF,"%d_bit",sizeof(long)*8);
  190. AddClassToHeap(VBUFF);
  191. Verbose("Additional hard class defined as: %s\n",VBUFF);
  192.  
  193. sprintf(VBUFF,"%s_%s",VSYSNAME.sysname,VSYSNAME.release);
  194. AddClassToHeap(CanonifyName(VBUFF));
  195.  
  196. Verbose("Additional hard class defined as: %s\n",VBUFF);
  197.  
  198. sprintf(VBUFF,"%s_%s",VSYSNAME.sysname,VSYSNAME.machine);
  199. AddClassToHeap(CanonifyName(VBUFF));
  200.  
  201. Verbose("Additional hard class defined as: %s\n",VBUFF);
  202.  
  203. sprintf(VBUFF,"%s_%s_%s",VSYSNAME.sysname,VSYSNAME.machine,VSYSNAME.release);
  204. AddClassToHeap(CanonifyName(VBUFF));
  205.  
  206. Verbose("Additional hard class defined as: %s\n",VBUFF);
  207.  
  208. #ifdef HAVE_SYSINFO
  209. #ifdef SI_ARCHITECTURE
  210. sz = sysinfo(SI_ARCHITECTURE,VBUFF,bufsize);
  211. if (sz == -1)
  212.   {
  213.   Verbose("cfengine internal: sysinfo returned -1\n");
  214.   }
  215. else
  216.   {
  217.   AddClassToHeap(CanonifyName(VBUFF));
  218.   Verbose("Additional hard class defined as: %s\n",VBUFF);
  219.   }
  220. #endif
  221. #endif
  222.  
  223. sprintf(VBUFF,"%s_%s_%s_%s",VSYSNAME.sysname,VSYSNAME.machine,VSYSNAME.release,VSYSNAME.version);
  224.  
  225. if (strlen(VBUFF) < maxvarsize-2)
  226.    {
  227.    strcpy(VARCH,CanonifyName(VBUFF));
  228.    }
  229. else
  230.    {
  231.    Verbose("cfengine internal: $(arch) overflows maxvarsize! Truncating\n");
  232.    strcpy(VARCH,CanonifyName(VSYSNAME.sysname));
  233.    }
  234.  
  235. AddClassToHeap(VARCH);
  236.  
  237. Verbose("Additional hard class defined as: %s\n",VARCH);
  238.  
  239. if (! found)
  240.    {
  241.    CfLog(cferror,"Cfengine: I don't understand what architecture this is!","");
  242.    }
  243.  
  244. strcpy(VBUFF,AUTOCONF_SYSNAME);
  245.  
  246. AddClassToHeap(CanonifyName(VBUFF));
  247.  
  248. Verbose("\nGNU autoconf class from compile time: %s\n\n",VBUFF);
  249. Verbose("  Careful with this - it might not be correct at run time if you have\n");
  250. Verbose("  several OS versions with binary compatibilty!\n\n");
  251.  
  252. /* Get IP address from nameserver */
  253.  
  254. if ((hp = gethostbyname(VSYSNAME.nodename)) == NULL)
  255.    {
  256.    return;
  257.    }
  258. else
  259.    {
  260.    bzero(&cin,sizeof(cin));
  261.    cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
  262.    Verbose("Address given by nameserver: %s\n",inet_ntoa(cin.sin_addr));
  263.    strcpy(VIPADDRESS,inet_ntoa(cin.sin_addr));
  264.    for (sp = VIPADDRESS+strlen(VIPADDRESS)-1; *sp != '.'; sp--)
  265.       {
  266.       }
  267.    *sp = '\0';
  268.    AddClassToHeap(CanonifyName(VIPADDRESS));
  269.  
  270.    strcpy(VIPADDRESS,inet_ntoa(cin.sin_addr));
  271.    AddClassToHeap(CanonifyName(VIPADDRESS));   
  272.    }
  273. }
  274.  
  275. /*********************************************************************/
  276. /* TOOLKIT : files/directories                                       */
  277. /**********************************************************************/
  278.  
  279. TruncateFile(name)
  280.  
  281. char *name;
  282.  
  283. { struct stat statbuf;
  284.   int fd;
  285.  
  286. if (stat(name,&statbuf) == -1)
  287.    {
  288.    Debug2("cfengine: didn't find %s to truncate\n",name);
  289.    return;
  290.    }
  291. else
  292.    {
  293.    if ((fd = creat(name,000)) == -1)      /* dummy mode ignored */
  294.       {
  295.       sprintf(OUTPUT,"creat(%s) failed\n",name);
  296.       CfLog(cferror,OUTPUT,"creat");
  297.       }
  298.    else
  299.       {
  300.       close(fd);
  301.       }
  302.    }
  303. }
  304.  
  305. /*************************************************************************/
  306.  
  307. FileSecure (name)
  308.  
  309. char *name;
  310.  
  311. { struct stat statbuf;
  312.  
  313. if (PARSEONLY || !CFPARANOID)
  314.    {
  315.    return true;
  316.    }
  317.  
  318. if (stat(name,&statbuf) == -1)
  319.    {
  320.    return false;
  321.    }
  322.  
  323. if (statbuf.st_uid != getuid())
  324.    {
  325.    sprintf(OUTPUT,"File %s is not owned by uid %d (security exception)",name,getuid());
  326.    CfLog(cferror,OUTPUT,"");
  327.    }
  328.  
  329. /* Is the file writable by ANYONE except the owner ? */
  330.  
  331. if (statbuf.st_mode & (S_IWGRP | S_IWOTH))
  332.    {
  333.    sprintf(OUTPUT,"File %s is writable by others (security exception)",name,getuid());
  334.    CfLog(cferror,OUTPUT,"");
  335.    return false;
  336.    }
  337.  
  338. return true; 
  339. }
  340. /***************************************************************/
  341.  
  342. ChecksumChanged(filename,digest,warnlevel,refresh)
  343.  
  344.     /* Returns false if filename never seen before, and adds a checksum
  345.        to the database. Returns true if checksums do not match and also
  346.        updates database to the new value */
  347.     
  348. char *filename;
  349. char digest[17];
  350. int warnlevel,refresh;
  351.  
  352. {     
  353. #if defined HAVE_LIBDB && (defined HAVE_DB_H || defined HAVE_DB_DB_H) && defined HAVE_DB_185_H
  354.   struct stat stat1, stat2;
  355.   int i, matched, needupdate = false;
  356.   DBT key,value;
  357.   DB *dbp;
  358.   DBC *dbcp;
  359.   db_recno_t recno;
  360.   char dbvalue[17],dbdigest[17];
  361.   time_t tloc;
  362.     
  363. Debug("ChecksumChanged: key %s in %s with data %s\n",filename,CHECKSUMDB,cfMDPrint(digest));
  364.  
  365.  if (CHECKSUMDB[0] == '\0')
  366.    {
  367.    if (ISCFENGINE)
  368.       {
  369.       CfLog(cferror,"(cfd) No database defined","");
  370.       return false;
  371.       }
  372.    else
  373.       {
  374.       Debug("Direct comparison (no db)\n");
  375.       cfMDFile(filename,dbdigest);
  376.       for (i = 0; i < 16; i++)
  377.      {
  378.      if (digest[i] != dbdigest[i])
  379.         {
  380.         return true;
  381.         }
  382.      }
  383.       return false;
  384.       }
  385.    }
  386.  
  387. if (refresh)
  388.    {
  389.    /* Check whether database is current wrt local file */
  390.  
  391.    if (stat(filename,&stat1) == -1)
  392.       {
  393.       sprintf(OUTPUT,"Couldn't stat %s\n",filename);
  394.       CfLog(cferror,OUTPUT,"stat");
  395.       return false;
  396.       }
  397.    
  398.    if (stat(CHECKSUMDB,&stat2) != -1)
  399.       {
  400.       if (stat1.st_mtime > stat2.st_mtime)
  401.      {
  402.      Debug("Checksum database is older than %s...refresh needed\n",filename);
  403.      needupdate = true;
  404.      }
  405.       else
  406.      {
  407.      Debug("Checksum up to date..\n");
  408.      }
  409.       }
  410.    else
  411.       {
  412.       needupdate = true;
  413.       }      
  414.    }
  415.  
  416.  /* Open the database. */
  417.  
  418. if ((errno = db_open(CHECKSUMDB,DB_BTREE, DB_CREATE, 0664, NULL, NULL, &dbp)) != 0)
  419.    {
  420.    sprintf(OUTPUT,"cfd: couldn't open checksum database %s\n",CHECKSUMDB);
  421.    CfLog(cferror,OUTPUT,"db_open");
  422.    Debug("Ended 2\n");
  423.    return false;
  424.    }
  425.  
  426. Debug("Opening database file %s\n",CHECKSUMDB); 
  427. bzero(&value,sizeof(value)); 
  428. bzero(&key,sizeof(key));       
  429.       
  430. key.data = filename;
  431. key.size = strlen(filename)+1;
  432. value.data = dbvalue;
  433. value.size = 17; 
  434.  
  435. if (needupdate)
  436.    {
  437.    cfMDFile(filename,dbdigest);
  438.    dbdigest[16] = '\0';
  439.    
  440.    key.data = filename;
  441.    key.size = strlen(filename)+1;
  442.    value.data = (void *) dbdigest;
  443.    value.size = 17;
  444.    
  445.    Debug("cfd: updating checksum for %s to %s\n",filename,cfMDPrint(value.data));
  446.    
  447.    if ((errno = dbp->del(dbp,NULL,&key,0)) != 0)
  448.       {
  449.       CfLog(cferror,"","db_store");
  450.       }
  451.   
  452.    key.data = filename;
  453.    key.size = strlen(filename)+1;
  454.    
  455.    if ((errno = dbp->put(dbp,NULL,&key,&value,0)) != 0)
  456.       {
  457.       CfLog(cferror,"put failed","db->put");
  458.       }      
  459.    }
  460.  
  461. if ((errno = dbp->get(dbp,NULL,&key,&value,0)) == 0)
  462.    {
  463.    /* The filename key was found in the db */
  464.    Debug("Comparing %s (sent) with %s (db)\n",cfMDPrint(digest),cfMDPrint(value.data));
  465.    bcopy(value.data,dbdigest,17);
  466.    
  467.    for (i = 0; i < 16; i++)
  468.       {
  469.       if (digest[i] != dbdigest[i])
  470.      {
  471.      Debug("cfd: Found checksum for %s in database but it didn't match\n",filename);
  472.  
  473.      CfLog(warnlevel,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!","");
  474.      sprintf(OUTPUT,"SECURITY ALERT: Checksum for %s changed!",filename);
  475.      CfLog(warnlevel,OUTPUT,"");
  476.      CfLog(warnlevel,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!","");
  477.  
  478.      if (CHECKSUMUPDATES)
  479.         {
  480.         cfMDFile(filename,dbdigest);
  481.         dbdigest[16] = '\0';
  482.         
  483.         key.data = filename;
  484.         key.size = strlen(filename)+1;
  485.         value.data = (void *) dbdigest;
  486.         value.size = 17;
  487.         
  488.         Debug("cfd: updating checksum for %s to %s\n",filename,cfMDPrint(value.data));
  489.         
  490.         if ((errno = dbp->del(dbp,NULL,&key,0)) != 0)
  491.            {
  492.            CfLog(cferror,"","db_store");
  493.            }
  494.         
  495.         key.data = filename;
  496.         key.size = strlen(filename)+1;
  497.         
  498.         if ((errno = dbp->put(dbp,NULL,&key,&value,0)) != 0)
  499.            {
  500.            CfLog(cferror,"put failed","db->put");
  501.            }
  502.         }
  503.  
  504.      dbp->close(dbp,0);
  505.      return true;                        /* Checksum updated but was changed */
  506.      }
  507.       }
  508.    
  509.    Debug("cfd: Found checksum for %s in database and it matched\n",filename);
  510.    dbp->close(dbp,0);
  511.    return false;
  512.    }
  513. else
  514.    {
  515.    /* Key was not found, so install it */
  516.    
  517.    cfMDFile(filename,dbdigest);
  518.    digest[16] = '\0';
  519.  
  520.    key.data = filename;
  521.    key.size = strlen(filename)+1;
  522.    value.data = (void *) dbdigest;
  523.    value.size = 17;
  524.  
  525.    Debug("cfd: storing checksum for %s in database %s\n",filename,cfMDPrint(dbdigest));
  526.  
  527.    if ((errno = dbp->put(dbp,NULL,&key,&value,0)) != 0)
  528.       {
  529.       CfLog(cferror,"put failed","db->put");
  530.       }
  531.    
  532.    dbp->close(dbp,0);
  533.  
  534.    if (ISCFENGINE)
  535.       {
  536.       return false;      /* No need to warn when first installed */
  537.       }
  538.    else
  539.       {
  540.       return true;
  541.       }
  542.    }
  543.  
  544. #else
  545. Verbose("cfd: No Berkeley DB2 database support available.\n");
  546. return false;
  547. #endif
  548. }
  549.  
  550. /*************************************************************************/
  551.  
  552. IgnoredOrExcluded(action,file,inclusions,exclusions)
  553.  
  554. enum actions action;
  555. char *file;
  556. struct Item *inclusions, *exclusions;
  557.  
  558. { char linkbuf[bufsize], *lastnode;
  559.  
  560. Debug("IgnoredOrExcluded(%s)\n",file);
  561.  
  562. if (strstr(file,"/"))
  563.    {
  564.    for (lastnode = file+strlen(file); *lastnode != '/'; lastnode--)
  565.       {
  566.       }
  567.  
  568.    lastnode++;
  569.    }
  570. else
  571.    {
  572.    lastnode = file;
  573.    }
  574.  
  575. if (inclusions != NULL && !IsWildItemIn(inclusions,lastnode))
  576.    {
  577.    Debug("cfengine: skipping non-included pattern %s\n",file);
  578.    return true;
  579.    }
  580.  
  581. switch(action)
  582.    {
  583.    case image:
  584.               if (IsWildItemIn(VEXCLUDECOPY,lastnode) || IsWildItemIn(exclusions,lastnode))
  585.                  {
  586.                  sprintf(OUTPUT,"Skipping excluded pattern %s\n",file);
  587.          CfLog(cfverbose,OUTPUT,"");
  588.                  return true;
  589.                  }
  590.    case links:
  591.               if (IsWildItemIn(VEXCLUDELINK,lastnode) || IsWildItemIn(exclusions,lastnode))
  592.                  {
  593.                  sprintf(OUTPUT,"kipping excluded pattern %s\n",file);
  594.          CfLog(cfverbose,OUTPUT,"");
  595.                  return true;
  596.                  }
  597.    default:
  598.               if (IsWildItemIn(exclusions,lastnode))
  599.                  {
  600.                  sprintf(OUTPUT,"Skipping excluded pattern %s\n",file);
  601.          CfLog(cfverbose,OUTPUT,"");
  602.                  return true;
  603.                  }       
  604.    }
  605.  
  606. return false;
  607. }
  608.  
  609.  
  610. /*********************************************************************/
  611.  
  612. Banner(string)
  613.  
  614. char *string;
  615.  
  616. {
  617. Verbose("---------------------------------------------------------------------\n");
  618. Verbose("%s\n",string);
  619. Verbose("---------------------------------------------------------------------\n\n");
  620. }
  621.  
  622.  
  623. /*********************************************************************/
  624.  
  625. SetDomainName(sp)           /* Bas van der Vlies */
  626.  
  627. char *sp;
  628.  
  629. { char fqn[maxvarsize];
  630.   char *ptr;
  631.   char buffer[bufsize];
  632.  
  633. if (gethostname(fqn, sizeof(fqn)) != -1)
  634.    {
  635.    strcpy(VFQNAME,fqn);
  636.    strcpy(buffer,VFQNAME);
  637.    AddClassToHeap(CanonifyName(buffer));
  638.    AddClassToHeap(CanonifyName(ToLowerStr(buffer)));
  639.  
  640.    if (strstr(fqn,"."))
  641.       {
  642.       ptr = strchr(fqn, '.');
  643.       strcpy(VDOMAIN, ++ptr);
  644.       }
  645.    }
  646.  
  647. if (strstr(VFQNAME,".") == 0)
  648.    {
  649.    strcat(VFQNAME,".");
  650.    strcat(VFQNAME,VDOMAIN);
  651.    }
  652.  
  653. AddClassToHeap(CanonifyName(VDOMAIN)); 
  654. }
  655.